/***************************************************************************
 创建者: 华磊
 开始时间: 2020.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2020.5.8 类的具体实现代码编写

 ***************************************************************************
 *  @file x.h
 *  功能:
 *
 *                                                                         *
 ***************************************************************************/
#ifndef ECATMOTOR_H
#define ECATMOTOR_H

#include "ecattype.h"
#include "stdio.h"
#include "GeneralDefine.h"
#include "logicmotor.h"

#define D_MAX_MOTOR_CHANNEL 4

/// LS警告宏定义
#define D_WARM_RST_PFAIL (0x01)    //主电源缺相
#define D_WARM_LOW_BATT (0x02)     //电池电量不足
#define D_WARM_OV_TCMD (0x04)      //扭矩指令过大
#define D_WARM_OV_VCMD (0x08)      //速度指令过大
#define D_WARM_OV_LOAD (0X10)      //超载警告
#define D_WARM_SETUP (0x20)        //选定容量
#define D_WARM_UD_VTG (0x40)       //低电压警告
#define D_WARM_EMG (0x80)          //EMG警告



/// 对象字典定义
//===input====
#define D_MAP_OBJECT_CONTROL_WORD       0x6040 //控制字
#define D_MAP_OBJECT_OPERATION_MODE     0x6060 //控制模式
#define D_MAP_OBJECT_TARGET_POSITION    0x607A //目标位置
#define D_MAP_OBJECT_TARGET_TORQUE      0x6071 //目标扭矩
#define D_MAP_OBJECT_TARGET_SPEED       0x60FF //目标速度
#define D_MAP_OBJECT_VELOCITY_OFFSET    0x60B1 // 速度漂移
#define D_MAP_OBJECT_TORQUE_OFFSET      0x60B2 //写扭矩漂移
#define D_MAP_OBJECT_HOME_METHOD  0x6098

//===output====
#define D_MAP_OBJECT_POSITION_ACTUAL    0x6064 //实际位置(编码器值)
#define D_MAP_OBJECT_TORQUE_ACTUAL      0x6077 //实际扭矩
#define D_MAP_OBJECT_VELOCITY_ACTUAL    0x606C //实际速度
#define D_MAP_OBJECT_STATUS_WORD        0x6041 //状态字
#define D_MAP_OBJECT_MODES_OF_OPERATION_DISPLAY 0x6061 //控制模式显示
#define D_MAP_OBJECT_DIGITAL_INPUT      0x60FD //数字输入
#define D_MAP_OBJECT_DIGITAL_OUTPUT     0x60FE //数字输出
#define D_MAP_OBJECT_ERROR_CODE_sanyo   0x2102 //三洋报警历史（32bit,取后8bit）
#define D_MAP_OBJECT_ERROR_CODE_603F    0x603F //错误码,三洋只能用sdo读

#define D_MAP_OBJECT_FOLLOWINGERROR_ACTUAL 0x60F4 // 实际跟随误差

#define D_MAP_OBJECT_QINGNENGDECHUAN_NULL_8BIT          0x5FFE //清能德创假字节，用于对齐

#define D_MAP_OBJECT_MODE_DISPLAY 0x6061
#define D_MAP_OBJECT_EXTERNAL_FEEDBACK 0x20b6 //外部编码器反馈
//#define D_MAP_OBJECT_ERROR_CODE_sanyo   0x1001 //错误码
//#define D_MAP_OBJECT_NULL_8BIT          0x0000 //三洋假字节，用于对齐
//#define D_MAP_OBJECT_NULL_8BIT          0x5FFE //假字节，用于对齐

//end 对象字典




////write
//    {0x6040, 0x00, 16},//控制字( 这个必须写在开头 )
//    {0x607A, 0x00, 32},//目标位置
//    {0x6060, 0x00, 8},// 控制模式
//    {0x0000, 0x00, 8},// 假字节 (三洋写了假字节后报错)

//    {0x60FF, 0x00, 32},//目标速度
//    {0x6071, 0x00, 16},//目标力距
//    {0x6098, 0x00, 8}, //回零模式
//    {0x6099, 0x01, 32},//回零速度 01寻找回零开关速度, 02寻找Z相速度
//    {0x6099, 0x02, 32},//回零速度 01寻找回零开关速度, 02寻找Z相速度
//    {0x60B1, 0x00, 32},//速度漂移
//    {0x60B2, 0x00, 16},//扭矩漂移
//    {0x609A, 0x00, 32},//LS err: not PDO

//// read
//    {0x6041, 0x00, 16},//状态字
//    {0x6064, 0x00, 32},//实际位置(编码器值)
//    {0x6061, 0x00, 8}, //控制模式显示
//    {0x0000, 0x00, 8}, //假字节
//    {0x606C, 0x00, 32},//实际速度
//    {0x6077, 0x00, 16},//实际扭矩
//    {0x60FD, 0x00, 32},//数字输入
//    {0x60F4, 0x00, 32},//实际跟随误差
//    {0x603F, 0x00, 16},//错误码

#define D_OD_NOT_USED  -1

/// 数据偏移,实际ＰＤＯ配置可以选下面的部分对象字典，没有配置的将不会进行数据读写
struct ec_off_od{
    //w
    unsigned int offsetControlWorldSet[D_MAX_MOTOR_CHANNEL]; //写控制字
    unsigned int offsetAmpModeSet[D_MAX_MOTOR_CHANNEL];      //控制模式
    unsigned int offsetTargetPosSet[D_MAX_MOTOR_CHANNEL];    //写目标位置
    unsigned int offsetTargetTorqueSet[D_MAX_MOTOR_CHANNEL]; //写目标扭矩
    unsigned int offsetTargetSpeedSet[D_MAX_MOTOR_CHANNEL];  //写目标速度
    unsigned int offsetTorqueOffSet[D_MAX_MOTOR_CHANNEL];    //写扭矩漂移,
    unsigned int offsetSpeedOffSet[D_MAX_MOTOR_CHANNEL];     //写速度漂移,
    unsigned int offsetHomeMethod[D_MAX_MOTOR_CHANNEL];


    //r
    unsigned int offsetErrorCodeGet[D_MAX_MOTOR_CHANNEL];    //读错误码
    unsigned int offsetServoStateGet[D_MAX_MOTOR_CHANNEL];   //读伺服状态
    unsigned int offsetEncoderGet[D_MAX_MOTOR_CHANNEL];      //读编码器
    unsigned int offsetSpeedGet[D_MAX_MOTOR_CHANNEL];        //读实际速度
    unsigned int offsetTorqueGet[D_MAX_MOTOR_CHANNEL];       //读实际力矩
    unsigned int offsetAmpModeGet[D_MAX_MOTOR_CHANNEL];      //读出来的控制模式
    unsigned int offsetFollowingErrorGet[D_MAX_MOTOR_CHANNEL]; //读跟随误差
    unsigned int offsetMotorDiGet[D_MAX_MOTOR_CHANNEL];      //读 di
    unsigned int offsetMotorDoGet[D_MAX_MOTOR_CHANNEL];      //读 do
    unsigned int offsetModeDisplay[D_MAX_MOTOR_CHANNEL];
    unsigned int offsetExternalFeedback[D_MAX_MOTOR_CHANNEL];//外部编码器反馈


    unsigned int offsetNullData8bitSet;   //写 假字节
} ;

/**
 * @brief The EcatMotor class 电机抽象类
 */
class EcatMotor
{
public:
    EcatMotor(E_DEVICE_PROTOCOL protocolIn, int aliasIn,int busIdIn,int maxChannelIn);


public:
    int checkEthercatDeviceError( bool &isWarningState,bool &isFaultOccurred,
                                  unsigned int &errorCodeOut,unsigned int &vendorIdOut,int &aliasOut);
    int checkCanopenDeviceError( bool &isWarningState,bool &isFaultOccurred,
                                  unsigned int &errorCodeOut,unsigned int &vendorIdOut,int &aliasOut);
    bool isErrorOccured();


    int setSdoList(QVector<SdoConfig> &sdoConfigListIn);
    int getSdoList(QVector<SdoConfig> &sdoConfigListOut);

    int getVendorId();//vendor id,要等到materPreOp才能加载进去
    int setVendorId(int vendorIdIn);

    int getAlias();
    int getProtocol();




    void updateMotorState();
    void updateEthercatMotorState(int channel);
    void updateModbusMotorState(int channel);

    /**
     * @brief addMsg  , 添加消息反馈    // 如果放在ethercat处理 , 用log缓存信息。外部周期处理
     * @param messageLevel
     * @param componentName
     * @param messageType
     * @param messageCode
     * @param robotId
     * @param parameter1
     * @param parameter2
     * @param parameter3
     * @param parameter4
     */
    void addMsg( int messageLevel,
                 std::string componentName,
                 std::string messageType,
                 int messageCode,
                 int _robotId,
                 int parameter1 = 0,
                 int parameter2 = 0,
                 int parameter3 = 0,
                 int parameter4 = 0 );


public:
    LogicMotor* logicMotors[D_MAX_MOTOR_CHANNEL];

    ec_off_od pdoDomainOffset;//pdo对象在过程域数据区的偏移地址。


public:
    E_DEVICE_PROTOCOL protocol;
    int alias;
    int busId;
    volatile unsigned int vendorId;
    int maxChannel;

private:
    QVector<SdoConfig> sdoConfigList;//ethercat使用




};

#endif // ECATMOTOR_H
